
require 'webrick/htmlutils'
require 'webrick/httputils'
require 'webrick/httpstatus'
require 'webrick/httpserver'

require 'appwiki/base/base_request.rb'

@@testlock = Mutex.new

class BaseRequestWebrick < BaseRequest

    attr_accessor :request_uri, :host, :path

    # parse request and return something that can emulate it as well
    def initialize(request,response,server)
      parse((request.body and StringIO.new(request.body)), H[request.meta_vars.to_hash] )
      @referer = @env['HTTP_REFERER']
      @content_type = 'text/html'
      @host = request.request_uri.host
      @request_uri = self
      @host = @@forcehostname if defined?(@@forcehostname) && @@forcehostname != nil
      @path = request.request_uri.path
      @request = request
      @response = response
    end

    # this method seems to never reply; falls off end of world; do it last.
    def set_redirect(value)
      @response.set_redirect(WEBrick::HTTPStatus::SeeOther,value)
    end

    def set_content_type(value)
      @content_type = value
    end

    def set_body(value)
      #@response['last-modified'] = @content_last_modified if @content_last_modified
      @response['Content-Type'] = @content_type if @content_type
      @response['Content-Length'] = value.length
      @response['Cache-Control'] = 'no-cache'
      @response['Pragma'] = 'no-cache'
      @response['Expires'] = '-1'
      @response.body = value
    end

    def set_cookies
      # send the cookie only if it did not arrive last time
      domainbase = @host.split('.')[-2..-1].join('.')
      value = @cookies.map { |k,v| "#{k}=#{escape(v)}; domain=.#{domainbase};  path=/" if v != @k[k] }.compact
      @response.header['Set-Cookie'] = value
    end

    def body=(value)
      @response.body=value
    end

    def []=(a,b)
      @response[a]=b
    end

    def [](a) 
      @response[a]
    end

    def method_missing(m,*a)
      puts "baserequestwebrick: method not found!!! #{m}"
    end

end

#
# webrick server abstraction for appwiki
#
class BaseServer < WEBrick::HTTPServer

  def service(request,response)
    # early out on options?
    if request.unparsed_uri == "*"
      if request.request_method == "OPTIONS"
        do_OPTIONS(request, response)
        raise WEBrick::HTTPStatus::OK
      end
      raise WEBrick::HTTPStatus::NotFound,"`#{request.unparsed_uri}' not found."
    end
    # call routers
    # TODO locking here is due to something with activerecord... examine.
    @@testlock.synchronize do
      request = BaseRequestWebrick.new(request,response,self)
      raise "something is terribly wrong #{request.path}" if !request.host
      # visit list of routes until one commands us to stop
      @@routes.each do |route|
        if route.resolve(request,request,self)
          break
        end
      end
    end
    return nil if true
    # failed to find any router?
    raise WEBrick::HTTPStatus::NotFound, "'#{request.path}' not found."
  end

  def self.run
    if @@debuglog
      l = WEBrick::Log.new('error.log')
      als = File.open('access.log','w')
      al = [[als,WEBrick::AccessLog::COMBINED_LOG_FORMAT]]
      s = BaseServer.new :Logger => l, :AccessLog => al, :Port => @@server_port, :BindAddress => @@server_ip
    else
      s = BaseServer.new :AccessLog => [], :Port => @@server_port, :BindAddress => @@server_ip 
    end
    trap(:INT) { s.shutdown }
    s.start
  end

end
